﻿using Define;
using Define.Attribute;
using LogicCenter.AssemblyPatch;
using LogicCenter.Logic;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using Tools.Base;

namespace LogicCenter
{
    partial class Program
    {
        public delegate void CmdCallback(string[] args);

        /// <summary>
        /// 帮助指令缓冲器 key-指令字符串 value-指令信息（Item1-指令说明 Item2-指令函数 Item3-指令函数运行结束后的回调函数）
        /// </summary>
        private static Dictionary<string, Tuple<string, Program.CmdCallback, AsyncCallback>> _CmdDict = new Dictionary<string, Tuple<string, CmdCallback, AsyncCallback>>(); 

        private static void ParseInputCmd(string strCmdValue)
        {
            LogManager.WriteLog(strCmdValue);

            string[] cmds = strCmdValue.Split(' ');
            if (cmds.Length == 0)
            {
                MyConsole.WriteLineEx("Please input valid cmd.", ConsoleColor.Red);
                return;
            }

            string cmdID = cmds[0];
            if (_CmdDict.TryGetValue(cmdID, out Tuple<string, CmdCallback, AsyncCallback> cb) && null != cb && null != cb.Item2)
            {
                string[] cmd_param = null;

                if (cmds.Length >= 2)
                {
                    cmd_param = new string[cmds.Length - 1];
                    for(int i = 1; i < cmds.Length; i++)
                    {
                        cmd_param[i - 1] = cmds[i];
                    }
                }

                //MyConsole.WriteLine(string.Format("{0}_{1}", "ParseInputCmd", Thread.CurrentThread.ManagedThreadId));
                cb.Item2.BeginInvoke(cmd_param, cb.Item3, cb.Item2);
                //cb.Item2.Invoke(cmd_param);
            }
            else
            {
                MyConsole.WriteLineEx("Please input valid cmd.", ConsoleColor.Red);
            }
        }

        /// <summary>
        /// 通用EndInvoke函数
        /// </summary>
        /// <param name="res"></param>
        private static void Cmd_EndInvoke_Normal(IAsyncResult res)
        {
            //MyConsole.WriteLine(string.Format("{0}_{1}", "Cmd_EndInvoke", Thread.CurrentThread.ManagedThreadId));
            CmdCallback func = (CmdCallback)res.AsyncState;
            try
            {
                func.EndInvoke(res);
            }
            catch(Exception ex)
            {
                LogManager.WriteLog(string.Format("探测到异常 {0}", ex.Message), ex, true);
            }
            finally
            {
                GC.Collect();
            }
        }

#region 注册控制台指令
        private static void InitCommonCmd()
        {
            MyConsole.WriteLineEx("输入help,打印帮助信息", ConsoleColor.Green);

            // 注册"帮助指令"
            _CmdDict.Add("help", new Tuple<string, CmdCallback, AsyncCallback>("打印帮助信息", CmdFunc_Help, Cmd_EndInvoke_Normal));

            // 注册"立即退出指令"
            _CmdDict.Add("close", new Tuple<string, CmdCallback, AsyncCallback>("立即退出", CmdFunc_Close, Cmd_EndInvoke_Normal));

            // 注册"创建宝箱指令"
            _CmdDict.Add("createbox", new Tuple<string, CmdCallback, AsyncCallback>("创建宝箱 参数1：数量", CmdFunc_CreateBoxInfo, Cmd_EndInvoke_Normal));

            // 注册"安全字典"
            _CmdDict.Add("safedic", new Tuple<string, CmdCallback, AsyncCallback>("测试安全字典", CmdFunc_SafeDic, Cmd_EndInvoke_Normal));

            // 注册"测试DateTime"
            _CmdDict.Add("datetime", new Tuple<string, CmdCallback, AsyncCallback>("测试DateTime", CmdFunc_DateTime, Cmd_EndInvoke_Normal));

            // 注册"测试DateTime"
            _CmdDict.Add("sortlist", new Tuple<string, CmdCallback, AsyncCallback>("测试list的sort以及Find函数", CmdFunc_SortList, Cmd_EndInvoke_Normal));

            // 注册"测试字典拷贝"
            _CmdDict.Add("diccopy", new Tuple<string, CmdCallback, AsyncCallback>("测试字典拷贝", CmdFunc_DicCopy, Cmd_EndInvoke_Normal));

            // 注册"Hook"
            _CmdDict.Add("hook", new Tuple<string, CmdCallback, AsyncCallback>("测试Hook", CmdFunc_Hook, Cmd_EndInvoke_Normal));

            // 注册"类型转换测试"
            _CmdDict.Add("type_change", new Tuple<string, CmdCallback, AsyncCallback>("测试对象类型转换", CmdFunc_TypeChange, Cmd_EndInvoke_Normal));

            // 注册"类型转换测试"
            _CmdDict.Add("singleton_test", new Tuple<string, CmdCallback, AsyncCallback>("测试模板调用", CmdFunc_Singleton_Test, Cmd_EndInvoke_Normal));

            // CmdFunc_AddPlayer
            _CmdDict.Add("addplayer", new Tuple<string, CmdCallback, AsyncCallback>("增加玩家", CmdFunc_AddPlayer, Cmd_EndInvoke_Normal));

            // CmdFunc_Other
            _CmdDict.Add("other", new Tuple<string, CmdCallback, AsyncCallback>("临时测试", CmdFunc_Other, Cmd_EndInvoke_Normal));

            // CmdFunc_Port
            _CmdDict.Add("port_conn_count", new Tuple<string, CmdCallback, AsyncCallback>("端口连接数", CmdFunc_Port_Conn_Count, Cmd_EndInvoke_Normal));

        }

        /// <summary>
        /// 帮助函数
        /// </summary>
        /// <param name="args"></param>
        private static void CmdFunc_Help(string[] args)
        {
            //MyConsole.WriteLine(string.Format("{0}_{1}", "CmdFunc_Help", Thread.CurrentThread.ManagedThreadId));
            foreach (var it in _CmdDict)
            {
                MyConsole.WriteLineEx(new string[] { it.Key, it.Value.Item1}, ConsoleColor.Cyan);
            }
        }

        private static void CmdFunc_Close(string[] args)
        {
            ExitServer();
        }

        private static Dictionary<int, List<BoxInfo>> _dic_box_info = new Dictionary<int, List<BoxInfo>>();
        private static long _nCurBoxDBID = 0;
        private static void CmdFunc_CreateBoxInfo(string[] args)
        {
            if(args == null || args.Length < 1)
            {
                MyConsole.WriteLineEx("参数不足", ConsoleColor.Red);
                return;
            }

            int nRoleCount = 0;
            if(!int.TryParse(args[0], out nRoleCount) || nRoleCount < 0)
            {
                MyConsole.WriteLineEx("参数不正确", ConsoleColor.Red);
                return;
            }

            DateTime tBegin = DateTime.Now;
            double fBeginMemory = SystemInfo.GetProcessMemory();
            Dictionary<int, List<BoxInfo>> dicBox = new Dictionary<int, List<BoxInfo>>();
            for(int i = 0; i < nRoleCount; i++)
            {
                dicBox[i] = new List<BoxInfo>();
                for(int j = 0; j < 5; j++)
                {
                    BoxInfo info = new BoxInfo();
                    info.nDBID = _nCurBoxDBID++;
                    info.nRoleID = i;
                    dicBox[i].Add(info);
                }                
            }
            _dic_box_info = dicBox;
            DateTime tEnd = DateTime.Now;
            double fEndMemory = SystemInfo.GetProcessMemory();
            MyConsole.WriteLineEx(string.Format("创建{0}个角色（每角色{1}个宝箱）完毕，耗时{2}ms，占用内存{3}MB", 
                nRoleCount, 5, (tEnd - tBegin).TotalMilliseconds, (fEndMemory - fBeginMemory)/1024), ConsoleColor.Green);
            
        }

        private static void CmdFunc_SafeDic(string[] args)
        {
            ConcurrentDictionary<int, BoxInfo> dic_box = new ConcurrentDictionary<int, BoxInfo>();
            //dic_box.TryGetValue()

            bool bHave = false;
            bool bLost = false;
            bool bGet = !bHave | bLost;
        }

        private static void CmdFunc_DateTime(string[] args)
        {
            if(true)
            {
                long nValue = MyTime.GetDateDayHourMinute(DateTime.Now);
                DateTime tValue = MyTime.ParseYearMonthDayHourMinute(0);
            }

            if(false)
            {
                DateTime tNew = DateTime.Now.AddMinutes(10);
                string strNew = tNew.ToString();
                MyConsole.WriteLineEx(string.Format("Now is {0}, new time is {1}", DateTime.Now.ToString(), strNew), ConsoleColor.Yellow);

                DateTime tGet;
                DateTime.TryParse(strNew, out tGet);
                MyConsole.WriteLineEx(string.Format("Now is {0}, get time is {1}", DateTime.Now.ToString(), tGet.ToString()), ConsoleColor.Yellow);

            }

            if (false)
            {
                DateTime t1 = DateTime.Parse("2019-07-23");
                DateTime t2 = DateTime.Parse("13:01:01");
                DateTime t3 = t2.AddDays(1);
                int nValue = t1.CompareTo(t2);

                MyConsole.WriteLineEx(nValue.ToString());

                DateTime tNow = DateTime.Now;
                string strNow = tNow.ToString("yyyy-MM-dd HH:mm:ss");
                MyConsole.WriteLineEx(strNow);
            }
        }

        private static void CmdFunc_SortList(string[] args)
        {
            List<RoleInfoForCompare> lsInfo = new List<RoleInfoForCompare>();

            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 1, bHaveBox = false, UnixTime = 160 });
            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 1, bHaveBox = true, UnixTime = 110 });
            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 1, bHaveBox = false, UnixTime = 100 });

            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 2, bHaveBox = false, UnixTime = 170 });
            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 2, bHaveBox = true, UnixTime = 121 });
            lsInfo.Add(new RoleInfoForCompare() { nRoleID = 2, bHaveBox = false, UnixTime = 120 });

            lsInfo.Insert(0,(new RoleInfoForCompare() { nRoleID = 3, bHaveBox = false, UnixTime = 150 }));
            lsInfo.Insert(0,(new RoleInfoForCompare() { nRoleID = 3, bHaveBox = false, UnixTime = 149 }));
            lsInfo.Insert(0,(new RoleInfoForCompare() { nRoleID = 3, bHaveBox = false, UnixTime = 148 }));

            lsInfo.Sort((x, y) => y.UnixTime.CompareTo(x.UnixTime));// 从大到小

            for(int i = 0; i < lsInfo.Count; i++)
            {
                MyConsole.WriteLine(string.Format("{0}", lsInfo[i].UnixTime));
            }

            List<RoleInfoForCompare> lsGet = lsInfo.FindAll(x => x.nRoleID == 0);
            if(lsGet == null)
            {
                MyConsole.WriteLine("lsGet == null");
            }
            else
            {
                MyConsole.WriteLine(string.Format("lsGet.count = {0}", lsGet.Count));
            }
        }

        private static void CmdFunc_DicCopy(string[] args)
        {
            Dictionary<long, double> dicSource = new Dictionary<long, double>();
            for (int i = 0; i < 10; i++)
            {
                dicSource[i] = i;
            }

            Dictionary<long, double> dicOther = new Dictionary<long, double>(dicSource);
            dicSource[5] = 500;
            dicSource[10] = 10;

            foreach(var it in dicSource)
            {
                MyConsole.WriteLine(string.Format("source key={0} value={1}", it.Key, it.Value));
            }
            foreach(var it in dicOther)
            {
                MyConsole.WriteLine(string.Format("other key={0} value={1}", it.Key, it.Value));
            }
        }

        private static void CmdFunc_Hook(string[] args)
        {
            MyConsole.WriteLine("Hook开始");

            //////////////////////////////////////////////////////////////////////////////////
            // 方式一：实验用的HotFix方式，此方式为验证HotFix可行性，属于实验性质。先注释掉。
            //////////////////////////////////////////////////////////////////////////////////
            //try
            //{
            //    Type rawType = typeof(NeedFixClass);
            //    MethodInfo rawMethodInfo = rawType.GetMethod("GetValue");

            //    Type hookType = typeof(HookClass);
            //    MethodInfo hookMethodInfo = hookType.GetMethod("GetMyValue");

            //    NeedFixClass t = new NeedFixClass();
            //    MyConsole.WriteLineEx(string.Format("OldValue = {0}", t.GetValue()), ConsoleColor.Green);

            //    int nRes = HotFixUtil.Fix(rawMethodInfo, hookMethodInfo, PactchSelect.Method1);
            //    if (nRes != HotFixErrCode.Sucess)
            //        nRes = HotFixUtil.Fix(rawMethodInfo, hookMethodInfo, PactchSelect.Method2);

            //    t = new NeedFixClass();
            //    MyConsole.WriteLineEx(string.Format("CurValue = {0}", t.GetValue()), ConsoleColor.Green);
            //}
            //catch(Exception ex)
            //{
            //    MyConsole.WriteLineEx(string.Format("Hook异常,msg={0}", ex.Message), ConsoleColor.Red);
            //}

            //////////////////////////////////////////////////////////////////////////////////
            // 方式二：通过加载动态库的方式进行Hook，此方式为正式游戏运行时Hook方式。
            //////////////////////////////////////////////////////////////////////////////////
            AssemblyPatchManager.Instance().Init();

            MyConsole.WriteLine("Hook完毕");
        }

        private static void CmdFunc_TypeChange(string[] args)
        {
            try
            {
                BoxInfo a = new BoxInfo();
                BoxInfoEx b = a as BoxInfoEx;

                MyConsole.WriteLineEx(string.Format("b = {0}", b == null ? "null" : b.ToString()), ConsoleColor.Green);
            }
            catch (Exception ex)
            {
                MyConsole.WriteLineEx(string.Format("CmdFunc_TypeChange Err. msg={0}", ex.Message), ConsoleColor.Red);
            }

        }

        private static void CmdFunc_Singleton_Test(string[] args)
        {
            {
                PlayerManager.Instance().InsertPlayer(1, "小明");

                // 通过另一种调用，说明两种调用方法都是指向同一个指针地址。
                int nPlayerCount = SingletonTemplate<PlayerManager>.Instance().GetPlayerCount();

                MyConsole.WriteLineEx(string.Format("单例{0}中的人员数量为{1}", PlayerManager.Instance(), nPlayerCount));

            }


            {
                SingletonTemplate<BoxInfo>.Instance().nBoxID = 9999;

                MyConsole.WriteLineEx(string.Format("单例{0}中的数据为{1}", 
                    SingletonTemplate<BoxInfo>.Instance(), SingletonTemplate<BoxInfo>.Instance().nBoxID));
            }
        }

        private static void CmdFunc_AddPlayer(string[] args)
        {
            {
                if (args.Length < 2)
                {
                    MyConsole.WriteLineEx("参数不足，应为2个参数[ID 名字]", ConsoleColor.Red);
                    return;
                }

                int nID = 0;
                int.TryParse(args[0], out nID);
                string strName = args[1];
                PlayerManager.Instance().InsertPlayer(nID, strName);
                MyConsole.WriteLineEx(string.Format("人员'{0}'加入成功 ", strName), ConsoleColor.Green);
            }
        }

        private static void CmdFunc_Port_Conn_Count(string[] args)
        {
            if(args.Length < 1)
            {
                MyConsole.WriteLineEx("参数不足，应为1个参数[Port]", ConsoleColor.Red);
                return;
            }

            int nPort = 0;
            int.TryParse(args[0], out nPort);

            MyConsole.WriteLineEx(string.Format("Port({0}) Connection Count = {1}.", nPort, PortTcpConnection(nPort)), ConsoleColor.Green);
        }

        public static int PortTcpConnection(int port)
        {
            IPGlobalProperties properti = IPGlobalProperties.GetIPGlobalProperties();
            var tcps = properti.GetActiveTcpConnections().ToList();

            var list = tcps.Where(f => f.LocalEndPoint.Port == port);

            var iplist = list.GroupBy(f => f.RemoteEndPoint.Address);
            return iplist.Count();
        }

        static Timer _timer = null;

        /// <summary>
        /// 所有临时的测试逻辑，添加在这里，但是需要注释好每一段的逻辑，以免混淆。
        /// </summary>
        /// <param name="args"></param>
        private static void CmdFunc_Other(string[] args)
        {
            if (args.Length == 0)
                return;

            int nCurTextIndex = -1;
            if (!int.TryParse(args[0], out nCurTextIndex))
            {
                MyConsole.WriteLineEx(string.Format("other <param1数字>"), ConsoleColor.Red);
                return;
            }

            // 测试案例说明：
            //      1.对字符串进行数字的补位处理；
            //      2.对字符串进行排序处理；
            if(nCurTextIndex == 1)
            {
                List<GoodsData> lsData = new List<GoodsData>();
                lsData.Add(new GoodsData(){ nQuality = 2, Categoriy = 1, nSuitID = 3, nGoodsID = 1, });
                lsData.Add(new GoodsData(){ nQuality = 1, Categoriy = 2, nSuitID = 5, nGoodsID = 2, });
                lsData.Add(new GoodsData(){ nQuality = 1, Categoriy = 2, nSuitID = 5, nGoodsID = 3, });

                GoodsData temp = lsData[2];
                lsData[2] = lsData[0];
                lsData[0] = temp;

                List<GoodsDataWitchIndex> lsIndex = new List<GoodsDataWitchIndex>();
                for(int i = 0; i < lsData.Count; i++)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append(lsData[i].nQuality.ToString().PadLeft(5, '0'));
                    sb.Append(lsData[i].Categoriy.ToString().PadLeft(5, '0'));
                    sb.Append(lsData[i].nSuitID.ToString().PadLeft(5, '0'));
                    sb.Append(lsData[i].nGoodsID.ToString().PadLeft(10, '0'));

                    lsIndex.Add(new GoodsDataWitchIndex() { strIndex = sb.ToString(), data = lsData[i] });
                }

                lsIndex.Sort((x, y) => y.strIndex.CompareTo(x.strIndex));

                for(int i = 0; i < lsIndex.Count; i++)
                {
                    MyConsole.WriteLineEx(lsIndex[i].strIndex);
                }
            }

            // 对字符串进行Encode和Decode操作
            if(nCurTextIndex == 2)
            {
                string strOld = "我们工会的轩辕是，Select * from table";
                string strNew = HttpUtility.UrlEncode(strOld);
                MyConsole.WriteLineEx(strNew);
                string strOO = HttpUtility.UrlDecode(strNew);
                MyConsole.WriteLineEx(strOO);
            }

            // 正则表达式
            if(nCurTextIndex == 3)
            {
                string strData = "我们我工会的宣言是：BC delete";

                bool bPass = RegexTools.ProcessSqlStr(strData);
                MyConsole.WriteLineEx(string.Format("检测结果为：{0}", bPass ? "通过" : "禁止"));

            }

            // 测试链表查询
            if(nCurTextIndex == 4)
            {
                List<Player> lsPlayer = new List<Player>();

                lsPlayer.Add(new Player() { nRoleID = 1, strName = "1" });
                lsPlayer.Add(new Player() { nRoleID = 2, strName = "2" });
                lsPlayer.Add(new Player() { nRoleID = 3, strName = "3" });

                bool bHave = lsPlayer.Contains(new Player() { nRoleID = 1, strName = "1" });
                lsPlayer.Remove(new Player() { nRoleID = 1, strName = "1" });

                Player p = lsPlayer.Find(x => x.nRoleID == 1 && x.strName == "1");
                if (p != null)
                    lsPlayer.Remove(p);

            }

            if(nCurTextIndex == 5)
            {
                double fTotalMoney = 124F;
                double fValue = fTotalMoney;
                int nCount = 0;
                CalculateMoney(ref fTotalMoney, 0.03, 0, ref nCount);
                MyConsole.WriteLineEx(string.Format("TotalMoney={0}, FinalMoney={1}, Count={2}", fValue, fTotalMoney, nCount));
  
            }

            if(nCurTextIndex == 6)
            {
                List<int> lsInt = new List<int>();
                List<long> lsLong = new List<long>();
                for(int i = 0; i < 5; i++)
                {
                    lsInt.Add(i);
                    lsLong.Add(i);
                }

                List<Player> lsPlayer = new List<Player>();

                lsPlayer.Add(new Player() { nRoleID = 1, strName = "1" });
                lsPlayer.Add(new Player() { nRoleID = 2, strName = "2" });
                lsPlayer.Add(new Player() { nRoleID = 3, strName = "3" });
                string strPlayer = NormalTool.ListToString(lsPlayer);
                MyConsole.WriteLineEx(strPlayer);

                string strInt = NormalTool.ListToString(lsInt);
                MyConsole.WriteLineEx(strInt);

                string strLong = NormalTool.ListToString(lsLong);
                MyConsole.WriteLineEx(strLong);
            }

            if(nCurTextIndex == 7)
            {
                MyConsole.WriteLineEx(string.Format("创建Timer的线程ID={0}", Thread.CurrentThread.ManagedThreadId));
                if (_timer == null)
                {
                    _timer = new Timer(TimerPorc, null, 0, 1000);
                }
            }

            if(nCurTextIndex == 8)
            {
                string[] strWorkerID = new string[10];
                for(int i = 0; i < strWorkerID.Length; i++)
                {
                    strWorkerID[i] = string.Format("{0}_name", i);
                }

                ArrayList arr = new ArrayList(strWorkerID);
                int nIndex_1 = arr.IndexOf("name");
                int nIndex_2 = arr.IndexOf("0_name");
                int nIndex_3 = arr.IndexOf("6_name");
            }

            // App.Config文件的使用示例
            if(nCurTextIndex == 9)
            {
                string strKey = "Name";
                string strValue = ConfigurationManager.AppSettings[strKey];
                if (!string.IsNullOrEmpty(strValue))
                    MyConsole.WriteLineEx(string.Format("App.config中的配置读取成功，key={0} value={1}", strKey, strValue), ConsoleColor.Green);

                strKey = "Name1";
                strValue = ConfigurationManager.AppSettings[strKey];
                if (!string.IsNullOrEmpty(strValue))
                    MyConsole.WriteLineEx(string.Format("App.config中的配置读取成功，key={0} value={1}", strKey, strValue), ConsoleColor.Green);

                strKey = "db_sy1";
                ConnectionStringSettings info = ConfigurationManager.ConnectionStrings[strKey];
                if (info != null)
                    MyConsole.WriteLineEx(string.Format("App.config中的配置读取成功，key={0} value={1}", strKey, info.ConnectionString), ConsoleColor.Green);

                strKey = "db_sy2";
                info = ConfigurationManager.ConnectionStrings[strKey];
                if (info != null)
                    MyConsole.WriteLineEx(string.Format("App.config中的配置读取成功，key={0} value={1}", strKey, info.ConnectionString), ConsoleColor.Green);

                strKey = "db_sy3";
                info = ConfigurationManager.ConnectionStrings[strKey];
                if (info != null)
                    MyConsole.WriteLineEx(string.Format("App.config中的配置读取成功，key={0} value={1}", strKey, info.ConnectionString), ConsoleColor.Green);
            }

            if(nCurTextIndex == 10)
            {
                string str1 = null;
                string str2 = "";
                string str3 = null;

                bool b1 = str1 == str2;
                bool b2 = str1 == str3;
            }
        }

        static void CalculateMoney(ref double fTotalMoney, double fRatPerYear, double fCostMoney, ref int nCount)
        {

            double fRatPerMonth = fRatPerYear / 12;
            fTotalMoney = fTotalMoney * (fRatPerMonth + 1) - fCostMoney;
            if (fTotalMoney < 0 || nCount > 240)
                return;
            nCount++;
            CalculateMoney(ref fTotalMoney, fRatPerYear, fCostMoney, ref nCount);
        }

        static void TimerPorc(object sender)
        {
            MyConsole.WriteLineEx(string.Format("执行Timer的线程ID={0}", Thread.CurrentThread.ManagedThreadId));
        }


        #endregion

    }
}
